package com.game;

import game.mina.IServer;

import game.mina.code.InnerServerProCodeFactor;
import game.mina.handler.ServerProHandler;
import game.server.Server;
import game.server.loader.ServerConfigXmlLoader;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

public abstract class ZZClientServer extends Server implements IServer {
	protected Logger log = Logger.getLogger(ZZClientServer.class);
	private ZZClientServerConfig clientServerConfig;
	protected NioSocketConnector socket = null;
	private ConcurrentHashMap<String, ConnectFuture> futures = new ConcurrentHashMap();

	protected ZZClientServer(String clientServerConfig, String serverConfig) {
		super(new ServerConfigXmlLoader().load(serverConfig));
		
		this.clientServerConfig = new ZZClientServerConfigXmlLoader().load(clientServerConfig);
	}

	public ZZServerInfo getServerInfoByTag(String tag) {
		List<ZZServerInfo> serverInfos = clientServerConfig.getConnectServers();
		for (ZZServerInfo si : serverInfos) {
			if ((si.getId() + "_" + si.getName()).equals(tag)) {
				return si;
			}
		}
		return null;
	}

	public ZZClientServerConfig getClientServerConfig() {
		return this.clientServerConfig;
	}

	public void run() {
		super.run();

		ZZClientServerConfig config = this.clientServerConfig;

		this.socket = new NioSocketConnector();
		this.socket.getFilterChain().addLast("codec", new ProtocolCodecFilter(new InnerServerProCodeFactor()));

		OrderedThreadPoolExecutor threadpool = new OrderedThreadPoolExecutor(500);
		this.socket.getFilterChain().addLast("threadPool", new ExecutorFilter(threadpool));

		int recsize = 524288;
		int sendsize = 1048576;

		SocketSessionConfig sc = this.socket.getSessionConfig();
		sc.setReceiveBufferSize(recsize);
		sc.setSendBufferSize(sendsize);

		sc.setSoLinger(0);

		this.socket.setHandler(new ServerProHandler(this));

		for (int i = 0; i < config.getConnectServers().size(); i++) {
			System.out.println("size = " + config.getConnectServers().size() + " i=" + i);
			ZZServerInfo info = (ZZServerInfo) config.getConnectServers().get(i);
			int connected = 0;
			if (info.getName().equals("1011_一代宗师")) {
				System.out.println();
			}
			System.out.println("try to register : " + info.getType() + "_" + info.getName());
			while (connected < 1) {
				ConnectFuture connect = this.socket.connect(new InetSocketAddress(info.getIp(), info.getPort()));
				connect.awaitUninterruptibly();
				if (!connect.isConnected()) {
					try {
						Thread.sleep(5000L);
					} catch (Exception e) {
						e.printStackTrace();
						this.log.error(e, e);
					}
				} else {
					register(info.getType());
					System.out.println("register : " + info.getType() + "_" + info.getName());
					futures.put(info.getType() + "_" + info.getName(), connect);
					connected++;
				}
				// else
				// {
				// IoSession session = connect.getSession();
				// session.setAttribute("connect-server-id",
				// Integer.valueOf(info.getId()));
				// session.setAttribute("connect-server-ip", info.getIp());
				// session.setAttribute("connect-server-port",
				// Integer.valueOf(info.getPort()));
				//
				// register(session, info.getType());
				//
				// connected++;
				// }
			}
		}
	}

	public Map<String, ConnectFuture> getFutures() {
		return futures;
	}

	public abstract void register(String paramString);
	// public abstract void register(IoSession paramIoSession, String
	// paramString);
}